package com.tabnet.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.tabnet.beans.produit.Etat;
import com.tabnet.beans.produit.GammeProduit;
import com.tabnet.beans.produit.Produit;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOFactory;
import com.tabnet.dao.DAOGammeProduit;
import com.tabnet.dao.DAOProduit;
import com.tabnet.dao.DAOUtilitaire;

public class GammeProduitDAOImpl implements DAOGammeProduit {
	
	private static final String SQL_SELECT_BY_ID  	= "SELECT * FROM GammeProduit WHERE Ref_GAM = ?";
	private static final String SQL_SELECT_DISPO  	= "SELECT * FROM GammeProduit WHERE Ref_GAM = ? AND DateMiseEnLigne <= NOW() "+
			"AND Etat_Ref = (SELECT Ref_Etat FROM Etat WHERE Description_Etat = 'Accepter')";
	private static final String SQL_SELECT_ALL_DISPO= "SELECT * FROM GammeProduit WHERE DateMiseEnLigne <= NOW() "+
			"AND Etat_Ref = (SELECT Ref_Etat FROM Etat WHERE Description_Etat = 'Accepter')";
	private static final String SQL_SELECT_ALL		= "SELECT * FROM GammeProduit";
	private static final String SQL_SELECT_LAST  	= "SELECT Ref_GAM FROM GammeProduit ORDER BY Ref_GAM DESC LIMIT 0 , 1";
	private static final String SQL_INSERT		  	= "INSERT INTO GammeProduit VALUES (?,?,?,?,?,?,?)";
	private static final String SQL_REFUS		  	= "UPDATE GammeProduit SET Description_GP = ? , Etat_Ref = (" +
			"SELECT Ref_Etat FROM Etat WHERE Description_Etat = 'Refuser') WHERE Ref_GAM = ?";
	
	private static final String SQL_ACCEPTER	  	= "UPDATE GammeProduit SET DateMiseEnLigne = ? , Etat_Ref = (" +
			"SELECT Ref_Etat FROM Etat WHERE Description_Etat = 'Accepter') WHERE Ref_GAM = ?";
	private static final String SQL_ACCEPTER_P	  	= "UPDATE Produit SET PuP = ? WHERE Ref_PRD = ?";
	
	private DAOFactory daoFactory;
	private DAOProduit daoProduit;
	
	public GammeProduitDAOImpl( DAOFactory daoFactory ) {
        this.daoFactory = daoFactory;
        daoProduit = daoFactory.getProduitDAO();
    }
	
	/**
     * <p>Fonction static map<br />
     * Simple méthode utilitaire permettant de faire la correspondance (le
     * mapping) entre une ligne issue de la table des gammes produits (un ResultSet) et
     * un bean GammeProduit.</p>
     * @param resultSet : objet ResultSet
     * @param dispo : vrai si le produit doit être disponible, false sinon
	 * @return objet GammeProduit
	 * @throws SQLException
     */
    private GammeProduit map( ResultSet resultSet, boolean dispo ) throws SQLException {
    	GammeProduit oGammeProduit = new GammeProduit();

    	oGammeProduit.setRef( resultSet.getString("Ref_GAM") );
    	oGammeProduit.setDescription( resultSet.getString("Description_GP") );
    	oGammeProduit.set_pInitial(resultSet.getDouble("PuInitial") );
    	oGammeProduit.setDtMiseEnLigne( resultSet.getDate("DateMiseEnLigne") );
    	oGammeProduit.setQteStockP( resultSet.getInt("QteInitialP") );

		try {
			Produit prod = this.daoFactory.getProduitDAO().trouverProduit(resultSet.getString("PRD_Ref"), dispo);
			oGammeProduit.setProduitG(prod);
		
			Etat etat = this.daoFactory.getEtatDAO().trouverEtat(resultSet.getString("Etat_Ref"));
			oGammeProduit.set_etat(etat);
		}
		catch (DAOException e) {
			e.printStackTrace();
		}
		
		return oGammeProduit;
    }
	
	@Override
	public void addGammeProduit(GammeProduit gammeP) throws DAOException {
		Connection connexion = null;
        PreparedStatement preparedStatementP = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
            connexion = daoFactory.getConnection();
            
            //Récupération du dernier numéro
            String strNewRef;
        	String strLastRef = this.getLastRef();
        	if(strLastRef == null)
        		strNewRef = "GP_0000001";
        	else if(strLastRef.length() == 10){
        		//Incrementation de cette derniere reference
        		String num = (Integer.parseInt(strLastRef.substring(5)) + 1) + ""; 
        		
        		while(num.length() < 7)
        			num = "0" + num;
        		
        		strNewRef = "GP_" + num;
        	}
        	else{
                throw new DAOException( "Échec de la récupération de la dernière référence." );
        	}
        	
        	gammeP.setRef(strNewRef);
        	
        	Etat etat = new Etat();
        	etat.setRef("ET_TEM");
        	etat.setDescription("Temporaire");
        	gammeP.set_etat(etat);
            
            daoProduit.addProduit(gammeP.getProduitG());
            
            //insertion
	        preparedStatementP = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_INSERT, true,
	        		gammeP.getRef(), gammeP.getDescription(), gammeP.getMiseEnLigne(), gammeP.get_pInitial(), 
	        		gammeP.getQteStockP(), gammeP.getProduitG().getRef(), gammeP.get_etat().getRef());
            int statut = preparedStatementP.executeUpdate();
            if ( statut == 0 ) {
                throw new DAOException( "Échec de la création de la gamme, aucune ligne ajoutée dans la table." );
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementP, connexion );
        }
		
	}

	@Override
	public void updGammeProduit(GammeProduit gammeP, String action) throws DAOException {
		Connection connexion = null;
        PreparedStatement preparedStatementP = null;
        ResultSet valeursAutoGenerees = null;
		
        if(action.equals("refus")){
	        try {
	            connexion = daoFactory.getConnection();
	            
	            // modification
		        preparedStatementP = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_REFUS, true,
		        		gammeP.getDescription(), gammeP.getRef());
	            int statut = preparedStatementP.executeUpdate();
	            if ( statut == 0 ) {
	                throw new DAOException( "Échec de la modification de la gamme, aucune ligne modifiée dans la table." );
	            }
	        } catch ( SQLException e ) {
	            throw new DAOException( e );
	        } finally {
	        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementP, connexion );
	        }
		}
        else {// modification de la date pour la gamme et du prix du produit
	        try {
	            connexion = daoFactory.getConnection();
	            PreparedStatement preparedStatement;
	            
	            // modification
		        preparedStatementP = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_ACCEPTER, true,
		        		gammeP.getMiseEnLigne(), gammeP.getRef());
		        int statut = preparedStatementP.executeUpdate();
	            if ( statut == 0 ) {
	                throw new DAOException( "Échec de la modification de la gamme, aucune ligne modifiée dans la table." );
	            }
	            
		        preparedStatement = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_ACCEPTER_P, true,
		        		gammeP.getProduitG().getPuP(), gammeP.getProduitG().getRef());
	            statut = preparedStatement.executeUpdate();
	            if ( statut == 0 ) {
	                throw new DAOException( "Échec de la modification de la gamme, aucune ligne modifiée dans la table." );
	            }
	        } catch ( SQLException e ) {
	            throw new DAOException( e );
	        } finally {
	        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementP, connexion );
	        }
        }
		
	}

	@Override
	public GammeProduit trouverGammeProduit(String ref, boolean dispo) throws DAOException {		
		// récupération des informations de la gamme
		Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        
        GammeProduit gammeP = new GammeProduit();
        gammeP.setRef(ref);
        
        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();

            if(dispo)
            	preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SELECT_DISPO, false, ref );
            else
                preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SELECT_BY_ID, false, ref );
            	
            resultSet = preparedStatement.executeQuery();
            /* Parcours de la ligne de données retournée dans le ResultSet */
            if ( resultSet.next() ) {
            	gammeP.setDescription( resultSet.getString("Description_GP") );
            	gammeP.set_pInitial(resultSet.getDouble("PuInitial") );
            	gammeP.setDtMiseEnLigne( resultSet.getDate("DateMiseEnLigne") );
            	gammeP.setQteStockP( resultSet.getInt("QteInitialP") );
            	
				Produit prod = daoFactory.getProduitDAO().trouverProduit(resultSet.getString("PRD_Ref"), dispo);
				gammeP.setProduitG(prod);
				
				Etat etat =  daoFactory.getEtatDAO().trouverEtat(resultSet.getString("Etat_Ref"));
				gammeP.set_etat(etat);
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, preparedStatement, connexion );
        }
		
		return gammeP;
	}

	@Override
	public Map<String, GammeProduit> getGammeProduits(boolean dispo) throws DAOException {		
		// récupération des informations de la gamme
		Connection oConnexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet oResultSet = null;
        
        GammeProduit oGammeProduit = null;
        Map<String, GammeProduit> mapGammeProduits = new HashMap<String, GammeProduit>();
        
        try {
            /* Récupération d'une connexion depuis la Factory */
        	oConnexion = daoFactory.getConnection();

            if(dispo)
            	preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT_ALL_DISPO, false);
            else
                preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT_ALL, false);
            	
            oResultSet = preparedStatement.executeQuery();
            
            /* Parcours de la ligne de données retournée dans le ResultSet */
            while ( oResultSet.next() ) {
            	oGammeProduit = map( oResultSet, dispo );
            	mapGammeProduits.put(oGammeProduit.getRef(), oGammeProduit);
            }
            
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( oResultSet, preparedStatement, oConnexion );
        }
		
		return mapGammeProduits;
	}
	
	public String getLastRef() throws SQLException, DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        
        String strRef = null;

        try {
        	oConnexion = daoFactory.getConnection();
        	
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT_LAST, false);
            resultSet = oPreparedStatement.executeQuery();
            
            if ( resultSet.next() )
            	strRef = resultSet.getString("Ref_GAM");
        }
        catch ( SQLException e ) {
            throw new DAOException(e);
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnexion );
        }

        return strRef;
    }

}
